﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BoneImp {
	class RotateTimeline : BaseTimeline {
		const int ROTATE_LAST_FRAME_TIME = -2;
		const int ROTATE_FRAME_VALUE = 1;

		public RotateTimeline(int frameCount) : base(frameCount, 2) {}

		public override void apply(SkeletonBase skeleton, float time, float alpha) {
			if (time < this.frames[0]) return; /* Time is before first frame. */

			Bone bone = skeleton.bones[this.boneIndex];

			if (time >= this.frames[this.framesLength - 2]) { /* Time is after last frame. */
				float amt = bone.data.rotation + this.frames[this.framesLength - 1] - bone.rotation;
				while (amt > 180)
					amt -= 360;
				while (amt < -180)
					amt += 360;
				bone.rotation += amt * alpha;
				return;
			}

			/* Interpolate between the last frame and the current frame. */
			int frameIndex = binarySearch(this.frames, this.framesLength, time, 2);
			float lastFrameValue = this.frames[frameIndex - 1];
			float frameTime = this.frames[frameIndex];
			float percent = 1 - (time - frameTime) / (this.frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
			percent = this.getCurvePercent(frameIndex / 2 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));

			float amount = this.frames[frameIndex + ROTATE_FRAME_VALUE] - lastFrameValue;
			while (amount > 180)
				amount -= 360;
			while (amount < -180)
				amount += 360;
			amount = bone.data.rotation + (lastFrameValue + amount * percent) - bone.rotation;
			while (amount > 180)
				amount -= 360;
			while (amount < -180)
				amount += 360;
			bone.rotation += amount * alpha;
		}

		public void setFrame(int frameIndex, float time, float angle) {
			frameIndex *= 2;
			this.frames[frameIndex] = time;
			this.frames[frameIndex + 1] = angle;
		}

		internal override float GetDuration() {
			float longest = 0;
			for (int i = 0; i < FrameCount; i++) {
				if (frames[i * 2] > longest) {
					longest = frames[i * 2];
				}
			}
			return longest;
		}
	}
}
